package cn.dansj.common.request.configure;

import cn.dansj.common.processor.TargetType;
import cn.dansj.common.processor.meta.WriteToResource;
import cn.dansj.common.request.annotation.logging.Nologging;
import cn.dansj.common.utils.enums.BooleanType;
import cn.dansj.common.utils.spring.context.ApplicationContextProvider;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotatedElementUtils;

import java.lang.reflect.Method;

@Aspect
@WriteToResource(type = TargetType.Imports, keyProperty = "org.springframework.boot.autoconfigure.AutoConfiguration")
@EnableAspectJAutoProxy
public class LoggerRecordConfiguration implements Ordered {
    private final LoggerRecord logRecord;

    public LoggerRecordConfiguration() {
        this.logRecord = ApplicationContextProvider.hasBean(LoggerRecord.class) ? ApplicationContextProvider.getBean(LoggerRecord.class) : DefaultBeanConfiguration.logRecord();
    }

    //监听所有带有RequestMappingMethod注解的controller
    @Around("@within(cn.dansj.common.request.annotation.http.RequestMappingMethod)&&(@annotation(cn.dansj.common.request.annotation.http.RequestMappingMethod)||@annotation(cn.dansj.common.request.annotation.http.GetMethod)||@annotation(cn.dansj.common.request.annotation.http.PostMethod))")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        return checkNologging(point) ? point.proceed() : logRecord.execute(point);
    }

    @Override
    public int getOrder() {
        return 10;
    }

    private boolean checkNologging(ProceedingJoinPoint point) {
        Signature signature = point.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        // 检查是否记录日志，不记录日志直接跳过，返回结果
        final Method method = methodSignature.getMethod();
        final Nologging methodNologging = AnnotatedElementUtils.findMergedAnnotation(method, Nologging.class);
        final Nologging classNologging = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), Nologging.class);
        final Nologging nologging = methodNologging != null && !BooleanType.UNSET.equals(methodNologging.value()) ? methodNologging : classNologging != null && !BooleanType.UNSET.equals(classNologging.value()) ? classNologging : null;
        return nologging != null && BooleanType.TRUE.equals(nologging.value());
    }
}
